using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Windows.Forms;
using RideMe.Core;
using System.Diagnostics;
using RideMe.Presentation.Controls;
using RideMe.CommandManagement;
using RideMe.Presentation.Properties;
using System.IO;

namespace RideMe.Presentation
{
    public partial class MainForm : Form
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="T:MainForm"/> class.
        /// </summary>
        public MainForm()
        {
            InitializeComponent();
            InitializeCommandManager();
            LoadLayout();
            LoadRecentProjects();
            UpdateStatus(Resources.ReadyStatus);
            HookProjectServiceEvents();
            LoadAddIns();

			SetupDragDrop();
			KeyPreview = true;
			KeyDown += new KeyEventHandler(MainForm_KeyDown);
        }

		private void SetupDragDrop()
		{
			AllowDrop = true;
			DragOver += new DragEventHandler(MainForm_DragOver);
			DragDrop += new DragEventHandler(MainForm_DragDrop);
		}

		void MainForm_DragDrop(object sender, DragEventArgs e)
		{
			string[] files = (string[])e.Data.GetData(DataFormats.FileDrop);

			foreach (string file in files)
			{
				ProjectService.AddOpenFile(file);
			}
		}

		void MainForm_DragOver(object sender, DragEventArgs e)
		{
			if (e.Data.GetDataPresent(DataFormats.FileDrop))
			{
				e.Effect = DragDropEffects.Move;
			}
		}

		void MainForm_KeyDown(object sender, KeyEventArgs e)
		{
			if (e.KeyCode == Keys.F1 && DocumentExplorerSelected && documentExplorer.ActiveTextEditorExists)
			{
				ICSharpCode.TextEditor.TextEditorControl te = documentExplorer.ActiveTextEditor;
				ICSharpCode.TextEditor.TextAreaControl tac = te.ActiveTextAreaControl;
				ICSharpCode.TextEditor.Document.IDocument doc = tac.TextArea.TextView.Document;
				string word = ICSharpCode.TextEditor.Document.TextUtilities.GetWordAt(doc, tac.Caret.Offset);

				if (!String.IsNullOrEmpty(word))
					Help.ShowHelp(this, HelpPath, HelpNavigator.KeywordIndex, word);
				
				e.Handled = true;
			}
		}

		private string HelpPath
		{
			get { return Path.Combine(Application.StartupPath, Resources.RailsDocFile); }
		}
		
        private CommandManager _commandManager;

        /// <summary>
        /// Gets a value indicating whether [document explorer selected].
        /// </summary>
        /// <value>
        /// 	<c>true</c> if [document explorer selected]; otherwise, <c>false</c>.
        /// </value>
        private bool DocumentExplorerSelected
        {
            get { return this.ActiveControl is DocumentExplorer; }
        }

        #region Command Management (giant)

        /// <summary>
        /// Initializes the command manager.
        /// </summary>
        private void InitializeCommandManager()
        {
            _commandManager = new CommandManager();

            this.components.Add(_commandManager);

            // I know I don't have to use the resource file for the 
            // command name, but I don't like string literals. 

			SetupFileCommands();
			SetupEditCommands();
			SetupTestingCommands();
			SetupViewCommands();
			SetupToolsCommands();
			SetupProjectCommands();
			SetupWindowCommands();

			SetupCommand(Resources.AddFolderCommand, AddFolderHandler, null, newFolderToolStripMenuItem);
			SetupCommand(Resources.RenameNodeCommand, RenameNodeHandler, null, renameToolStripMenuItem);
			SetupCommand(Resources.OpenNonProjectFileCommand,OpenNonProjectFileHander, null, openFileToolStripMenuItem, openFileToolStripButton );
            SetupCommand(Resources.AboutCommand,AboutHandler, null, aboutToolStripMenuItem);
            SetupCommand(Resources.RailsDocumentationCommand, RailsDocumentationHandler, null, railsDocumentationToolStripMenuItem);

        }

		private void SetupWindowCommands()
		{
			SetupCommand(Resources.WindowCloseAllButThisCommand, WindowCloseAllButThisHandler, UpdateWindowCloseAllButThisHandler, closeAllButThisToolStripMenuItem);
			SetupCommand(Resources.WindowCloseAllCommand, WindowCloseAllHandler, UpdateWindowCloseAllHandler, closeAllToolStripMenuItem);
			SetupCommand(Resources.WindowCloseCommand, WindowCloseHandler, UpdateWindowCloseHandler, closeToolStripMenuItem);
			SetupCommand(Resources.WindowSplitCommand, WindowSplitHandler, UpdateWindowSplitHandler, splitToolStripMenuItem);

		}

		private void SetupViewCommands()
		{
			SetupCommand(Resources.ViewProjectExplorerCommand, ViewProjectExplorerHandler, null, projectExplorerToolStripMenuItem, viewProjectExplorerToolStripButton);
			SetupCommand(Resources.ViewOutputCommand, ViewOutputHandler, null, outputWindowToolStripMenuItem, viewOutputToolStripButton);
			SetupCommand(Resources.ViewPropertiesWindowCommand, ViewPropertiesWindowHandler, null, propertiesWindowToolStripMenuItem, viewPropertiesToolStripButton);

			SetupCommand(Resources.ProjectStatsCommand, ViewProjectStatsHandler, UpdateProjectOpenHandler, projectStatsToolStripMenuItem);
		}

		private void SetupProjectCommands()
		{
			SetupCommand(Resources.PrepareForUnixCommand, PrepareForUnixHandler, UpdateProjectOpenHandler, prepareToRunOnUnixToolStripMenuItem);
			SetupCommand(Resources.PrepareForWindowsCommand, PrepareForWindowsHandler, UpdateProjectOpenHandler, prepareToRunOnWindowsToolStripMenuItem);
			SetupCommand(Resources.StartCommand, StartHandler, UpdateProjectOpenAndRunningHandler, startToolStripMenuItem, startToolStripButton);
			SetupCommand(Resources.StopCommand, StopProjectHandler, UpdateStopProjectHandler, stopStripMenuItem, stopToolStripButton);
		}

		private void SetupToolsCommands()
		{
			SetupCommand(Resources.OptionsCommand, ShowOptionsHandler, null, optionsToolStripMenuItem);
			SetupCommand(Resources.CheckSyntaxCommand, CheckSyntaxHandler, UpdateCheckSyntaxHandler, checkSyntaxToolStripMenuItem);
			SetupCommand(Resources.CodeSnippetManagerCommand, CodeSnippetManagerHandler, null, codeSnippetManagerToolStripMenuItem);
			SetupCommand(Resources.RunMigrationCommand, RunMigrationHandler, UpdateProjectOpenHandler, runMigrationToolStripMenuItem);
			SetupCommand(Resources.RunMigrationWithTrace, RunMigrationWithTraceHandler, UpdateProjectOpenHandler, runMigrationTraceToolStripMenuItem);
		}

		private void SetupTestingCommands()
		{
		    SetupCommand(Resources.RunAllTestsCommand, RunAllTestsHandler, UpdateProjectOpenHandler, runAllTestsToolStripMenuItem);
            SetupCommand(Resources.RunAllTestsTraceCommand, RunAllTestsWithTraceHandler, UpdateProjectOpenHandler, runAllTestsTraceToolStripMenuItem);
		    SetupCommand(Resources.RunAllUnitTestsCommand, RunAllUnitTestsHandler, UpdateProjectOpenHandler, runAllUnitTestsToolStripMenuItem);
            SetupCommand(Resources.RunAllUnitTestsTraceCommand, RunAllUnitTestsWithTraceHandler, UpdateProjectOpenHandler, runAllUnitTestsTraceToolStripMenuItem);
			SetupCommand(Resources.RunAllFunctionalTestsCommand, RunAllFunctionalTestsHandler, UpdateProjectOpenHandler, runAllFunctionalTestsToolStripMenuItem);
			SetupCommand(Resources.RunAllFunctionalTestsTraceCommand, RunAllFunctionalTestsWithTraceHandler, UpdateProjectOpenHandler, runAllFunctionalTestsTraceToolStripMenuItem);
            SetupCommand(Resources.RunAllIntegrationTestsCommand, RunAllIntegrationTestsHandler, UpdateProjectOpenHandler, runAllIntegrationTestsToolStripMenuItem);
            SetupCommand(Resources.RunAllIntegrationTestsTraceCommand, RunAllIntegrationTestsWithTraceHandler, UpdateProjectOpenHandler, runAllIntegrationTestsTraceToolStripMenuItem);
			SetupCommand(Resources.RunTestsForFileCommand, RunTestsForPathHandler, UpdateFileHandler, runTestsContextToolStripMenuItem);
		}
        private void SetupEditCommands()
		{
			SetupCommand(Resources.FindCommand, FindHandler, UpdateProjectOpenHandler, findToolStripMenuItem);
			SetupCommand(Resources.ReplaceCommand, ReplaceHandler, UpdateProjectOpenHandler, replaceToolStripMenuItem);
			SetupCommand(Resources.UndoCommand, UndoHandler, UpdateUndoHandler, undoToolStripButton, undoToolStripMenuItem);
			SetupCommand(Resources.RedoCommand, RedoHandler, UpdateRedoHandler, redoToolStripMenuItem, redoToolStripButton);
			SetupCommand(Resources.DeleteCommand, DeleteHandler, UpdateFileHandler, deleteToolStripMenuItem, deletedContextToolStripMenuItem);
			SetupCommand(Resources.CutCommand, CutHandler, UpdateCanCutHandler, cutToolStripMenuItem, cutContextToolStripMenuItem, cutToolStripButton);
			SetupCommand(Resources.CopyCommand, CopyHandler, UpdateCanCopyPasteHandler, copyToolStripMenuItem, copyContextToolStripMenuItem, copyToolStripButton, copyProjectExplorerContextToolStripMenuItem);
			SetupCommand(Resources.ToggleFoldCommand, ToggleFoldHandler, UpdateRubyFileSelectedHandler, toggleFoldToolStripMenuItem);
            SetupCommand(Resources.ToggleAllFoldsCommand, ToggleAllFoldingHandler, UpdateRubyFileSelectedHandler, toggleAllFoldsToolStripMenuItem);
            SetupCommand(Resources.ShowDefinitionsOnlyCommand, ShowDefinitionsOnlyHandler, UpdateRubyFileSelectedHandler, showDefinitionsOnlyToolStripMenuItem);
			SetupCommand(Resources.PasteCommand, PasteHandler, UpdateCanCopyPasteHandler, pasteToolStripMenuItem, pasteContextToolStripMenuItem, pasteToolStripButton, pasteProjectExplorerContextToolStripMenuItem);
			SetupCommand(Resources.GoToControllerDocumentContextCommmand, GoToControllerHandler, UpdateGoToControllerHandler, goToControllerToolStripMenuItem);
			SetupCommand(Resources.GoToModelDocumentContextCommand, GoToModelHandler, UpdateGoToModelHandler, goToModelToolStripMenuItem);
			SetupCommand(Resources.GoToViewDocumentContextCommand, GoToViewHandler, UpdateGoToViewHandler, goToViewToolStripMenuItem);
			SetupCommand(Resources.EditGoToFileCommand, GoToFileHandler, UpdateProjectOpenHandler, goToFileToolStripMenuItem);
			SetupCommand(Resources.CommentUnCommentCommand, ToggleCommentHandler, UpdateToggleCommentHandler, toggleCommentToolStripButton, blockCommentOrUncommentToolStripMenuItem);
            SetupCommand(Resources.ClearOutputWindowCommand, ClearOutputWindowHandler, null, clearOutputWindowToolStripMenuItem);
            SetupCommand(Resources.ReplaceTabsWithSpacesCommand, ReplaceTabsWithSpacesHandler, UpdateFileOpenHandler, replaceTabsWithSpacesToolStripMenuItem);
        }

		private void SetupFileCommands()
		{
			SetupCommand(Resources.RecentProjectsCommand, null, UpdateRecentProjectsHandler, recentProjectsToolStripMenuItem);
			SetupCommand(Resources.OpenProjectCommand, OpenProjectHandler, null, openProjectToolStripMenuItem, openProjectToolStripButton);
            SetupCommand(Resources.OpenFileCommand,OpenFileHandler, UpdateFileHandler, openContextToolStripItem);
			SetupCommand(Resources.NewProjectCommand, NewProjectHandler, null, newProjectToolStripMenuItem, newProjectToolStripButton);
			SetupCommand(Resources.CloseProjectCommand, CloseProjectHandler, UpdateCloseHandler, closeProjectToolStripMenuItem);
			SetupCommand(Resources.ExitCommand, ExitHandler, null, exitToolStripMenuItem);
			SetupCommand(Resources.SaveCommand, SaveHandler, UpdateSaveHandler, saveToolStripMenuItem, saveToolStripButton);
			SetupCommand(Resources.SaveAsCommand, SaveAsHandler, UpdateSaveHandler, saveAsToolStripMenuItem);
			SetupCommand(Resources.SaveAllCommand, SaveAllHandler, UpdateSaveHandler, saveAllToolStripMenuItem, saveAllToolStripButton);
			SetupCommand(Resources.GenerateModelCommand, GenerateModelHandler, UpdateProjectOpenHandler, modelToolStripMenuItem);
			SetupCommand(Resources.GenerateControllerCommand, GenerateControllerHandler, UpdateProjectOpenHandler, controllerToolStripMenuItem);
			SetupCommand(Resources.GenerateScaffoldCommand, GenerateScaffoldHandler, UpdateProjectOpenHandler, scaffoldToolStripMenuItem);
			SetupCommand(Resources.GenerateMigrationCommand, GenerateMigrationHandler, UpdateProjectOpenHandler, migrationToolStripMenuItem);
			SetupCommand(Resources.GenerateMailerCommand, GenerateMailerHandler, UpdateProjectOpenHandler, mailerToolStripMenuItem);
			SetupCommand(Resources.NewMiscGeneratorCommand, MiscGeneratorHandler, UpdateProjectOpenHandler, miscGeneratorToolStripMenuItem);
			SetupCommand(Resources.DestroyModelCommand, DestroyModelHandler, UpdateProjectOpenHandler, destroyModelToolStripMenuItem);
			SetupCommand(Resources.DestroyControllerCommand, DestroyControllerHandler, UpdateProjectOpenHandler, destroyControllerToolStripMenuItem);
			SetupCommand(Resources.DestroyScaffoldCommand, DestroyScaffoldHandler, UpdateProjectOpenHandler, destroyScaffoldToolStripMenuItem);
			SetupCommand(Resources.DestroyMigrationCommand, DestroyMigrationHandler, UpdateProjectOpenHandler, destroyMigrationToolStripMenuItem);
			SetupCommand(Resources.DestroyMailerCommand, DestroyMailerHandler, UpdateProjectOpenHandler, destroyMailerToolStripMenuItem);
			SetupCommand(Resources.DestroyMiscGeneratorCommand, DestroyMiscGeneratorHandler, UpdateProjectOpenHandler, destroyMiscGeneratorToolStripMenuItem);
            SetupCommand(Resources.NewItemCommand, AddProjectItemHandler, UpdateAddProjectItemHandler, newItemToolStripMenuItem, addNewItemContextToolStripMenuItem);
            SetupCommand(Resources.NewRhtmlPageCommand, AddRhtmlPageHandler, UpdateAddProjectItemHandler, newRhtmlPageToolStripMenuItem, addNewRhtmlPageContextToolStripMenuItem);
            SetupCommand(Resources.NewRjsTemplateCommand, AddRjsTemplateHandler, UpdateAddProjectItemHandler, newRjsTemplateToolStripMenuItem, addNewRjsTemplateContextToolStripMenuItem);
            SetupCommand(Resources.PrintCommand, PrintHandler, UpdateFileOpenHandler, printToolStripMenuItem);
        }

        private void SetupCommand(string text, EventHandler executor, EventHandler updater, params object[] ui)
        {
            _commandManager.Commands.Add(new Command(text, executor, updater));
            _commandManager.Commands[text].CommandInstances.Add(ui);
        }
        
        #endregion

        /// <summary>
        /// Loads the layout.
        /// </summary>
        private void LoadLayout()
        {
            if (File.Exists(Resources.LayoutFileName))
            {
                sandDockManager.SetLayout(FileSystemService.GetDocumentText(Resources.LayoutFileName));
            }
        }

        /// <summary>
        /// This loads the controls for the loaded add-ins
        /// </summary>
        private void LoadAddIns()
        {
            RideMe.AddIns.AddInService.Init();
            RideMe.AddIns.Base.ApplicationContext.Current.UserInterfaceEvents.OnMenuCreated(
                new RideMe.AddIns.Events.UserInterfaceEventSource.MenuCreatedEventArgs(this.menuStrip));
            RideMe.AddIns.Base.ApplicationContext.Current.UserInterfaceEvents.OnLeftDockControlCreated(
                new RideMe.AddIns.Events.UserInterfaceEventSource.DockControlCreatedEventArgs(this.leftSandDock));
            RideMe.AddIns.Base.ApplicationContext.Current.UserInterfaceEvents.OnRightDockControlCreated(
                new RideMe.AddIns.Events.UserInterfaceEventSource.DockControlCreatedEventArgs(this.rightSandDock));
            RideMe.AddIns.Base.ApplicationContext.Current.UserInterfaceEvents.OnBottomDockControlCreated(
                new RideMe.AddIns.Events.UserInterfaceEventSource.DockControlCreatedEventArgs(this.bottomSandDock));
            RideMe.AddIns.Base.ApplicationContext.Current.UserInterfaceEvents.OnOutputWindowControlCreated(
                new RideMe.AddIns.Events.UserInterfaceEventSource.ControlCreatedEventArgs(this.outputWindow));

            if (this.leftSandDock.Controls.Count == 0)
            {
                this.leftSandDock.Visible = false;
            }
        }

        /// <summary>
        /// Hooks the project service events.
        /// </summary>
        private void HookProjectServiceEvents()
        {
            ProjectService.TaskCompleted += new EventHandler(ProjectService_GeneratingComplete);
            ProjectService.RecentProjectAdded += new EventHandler<ProjectPathChangedEventArgs>(ProjectService_RecentProjectAdded);
            ProjectService.RecentProjectRemoved += new EventHandler<ProjectPathChangedEventArgs>(ProjectService_RecentProjectRemoved);
            ProjectService.EditorCaretPositionChanged += new EventHandler<CaretPositionChangedEventArgs>(ProjectService_EditorCaretPositionChanged);
            ProjectService.LastDocumentClosed += new EventHandler(ProjectService_LastDocumentClosed);
            ProjectService.ProjectPathChanged += new EventHandler<ProjectPathChangedEventArgs>(ProjectService_ProjectPathChanged);
            ProjectService.ProjectClosed += new EventHandler(ProjectService_ProjectClosed);
            ProjectService.WebServerStarted += new EventHandler(ProjectService_WebServerStarted);
            ProjectService.SelectedFileChanged += new EventHandler<SelectedFileChangedEventArgs>(ProjectService_SelectedFileChanged);
            ProjectService.TabChanged += new EventHandler<ProjectFileEventArgs>(ProjectService_TabChanged);
            ProjectService.PreparedForServer += new EventHandler<ProjectFileEventArgs>(ProjectService_PreparedForServer);
            ProjectService.RakeOutputReceived += new EventHandler<RakeEventArgs>(ProjectService_StatsRecieved);
            ProjectService.ProjectLoaded += new EventHandler<ProjectLoadedEventArgs> (ProjectService_ProjectLoaded);
			ProjectService.ProjectStarted += new EventHandler(ProjectService_ProjectStarted);
			ProjectService.ProjectStopped += new EventHandler(ProjectService_ProjectStopped);
			ProjectService.WebServerStarting += new EventHandler(ProjectService_WebServerStarting);
			ProjectService.LogErrorFound += new EventHandler<LogFileWatcher.RailsLogFileEventArgs>(ProjectService_LogErrorFound);
            ProjectService.ErrorRecieved += new EventHandler<DataReceivedEventArgs>(ErrorReceivedHandler);
            ProjectService.FileClosed += new EventHandler<ProjectFileEventArgs>(ProjectService_FileClosed);
            ProjectService.FileOpened += new EventHandler<ProjectFileEventArgs>(ProjectService_FileOpened);
            ProjectService.FileRenamed += new EventHandler<FileRenameEventArgs>(ProjectService_FileRenamed);
            ProjectService.FileDeleted += new EventHandler<ProjectFileEventArgs>(ProjectService_FileDeleted);
        }

        /// <summary>
        /// Free up event handles for ProjectService events.
        /// This is called in the Dispose method.
        /// </summary>
        private void UnhookProjectServiceEvents()
        {
            ProjectService.TaskCompleted -= new EventHandler(ProjectService_GeneratingComplete);
            ProjectService.RecentProjectAdded -= new EventHandler<ProjectPathChangedEventArgs>(ProjectService_RecentProjectAdded);
            ProjectService.RecentProjectRemoved -= new EventHandler<ProjectPathChangedEventArgs>(ProjectService_RecentProjectRemoved);
            ProjectService.EditorCaretPositionChanged -= new EventHandler<CaretPositionChangedEventArgs>(ProjectService_EditorCaretPositionChanged);
            ProjectService.LastDocumentClosed -= new EventHandler(ProjectService_LastDocumentClosed);
            ProjectService.ProjectPathChanged -= new EventHandler<ProjectPathChangedEventArgs>(ProjectService_ProjectPathChanged);
            ProjectService.ProjectClosed -= new EventHandler(ProjectService_ProjectClosed);
            ProjectService.WebServerStarted -= new EventHandler(ProjectService_WebServerStarted);
            ProjectService.SelectedFileChanged -= new EventHandler<SelectedFileChangedEventArgs>(ProjectService_SelectedFileChanged);
            ProjectService.FileRenamed -= new EventHandler<FileRenameEventArgs>(ProjectService_FileRenamed);
            ProjectService.TabChanged -= new EventHandler<ProjectFileEventArgs>(ProjectService_TabChanged);
            ProjectService.PreparedForServer -= new EventHandler<ProjectFileEventArgs>(ProjectService_PreparedForServer);
            ProjectService.ProjectLoaded -= new EventHandler<ProjectLoadedEventArgs>(ProjectService_ProjectLoaded);
            ProjectService.ProjectStarted -= new EventHandler(ProjectService_ProjectStarted);
            ProjectService.ProjectStopped -= new EventHandler(ProjectService_ProjectStopped);
            ProjectService.WebServerStarting -= new EventHandler(ProjectService_WebServerStarting);
			ProjectService.LogErrorFound -= new EventHandler<LogFileWatcher.RailsLogFileEventArgs>(ProjectService_LogErrorFound);
		}

        /// <summary>
        /// Unhooks the recent project menu item handlers.
        /// </summary>
        private void UnhookRecentProjectMenuItemHandlers()
        {
            foreach (ToolStripMenuItem menuItem in recentProjectsToolStripMenuItem.DropDownItems)
            {
                menuItem.Click -= new EventHandler(recentProjectMenuItem_click);
            }
        }

		/// <summary>
		/// Opens a tabbed window with an embedded browser;
		/// </summary>
		private void OpenBrowser()
		{
			if (InvokeRequired)
			{
				Invoke(new MethodInvoker(OpenBrowser));
			}
			else
			{
				documentExplorer.OpenBrowser();
			}
		}

		/// <summary>
		/// Opens a tabbed window with an embedded browser;
		/// </summary>
		private void CloseBrowser()
		{
			if (InvokeRequired)
			{
				Invoke(new MethodInvoker(CloseBrowser));
			}
			else
			{
				documentExplorer.CloseBrowser();
			}
		}

        /// <summary>
        /// Displays the server ballon after the web server is started.
        /// </summary>
        private void DisplayServerBallon()
        {
            notifyIcon.BalloonTipText = string.Format(Resources.WebServerStarted, Options.Instance.ServerPort);
            notifyIcon.Visible = true;
            notifyIcon.ShowBalloonTip(10);
        }

        /// <summary>
        /// Updates the line column status.
        /// </summary>
        /// <param name="line">The line.</param>
        /// <param name="column">The column.</param>
        private void UpdateLineColumnStatus(string line, string column)
        {
            lineToolStripStatusLabel.Text = line;
            columnToolStripStatusLabel.Text = column;
        }

        /// <summary>
        /// Shows the generator dialog.
        /// </summary>
        /// <param name="commandName">Name of the command.</param>
        /// <param name="usage">The usage.</param>
        /// <returns></returns>
        private string ShowGeneratorDialog(string commandName, string usage)
        {
            using (GeneratorDialog generatorDialog = new GeneratorDialog())
            {
                generatorDialog.CommandName = commandName;
                generatorDialog.UsageLabel = usage;

                string generatorCommand = string.Empty;
                if (generatorDialog.ShowDialog() != DialogResult.Cancel)
                {
                    generatorCommand =  generatorDialog.GeneratorCommand;
                }

                return generatorCommand;
            }
        }

        /// <summary>
        /// Shows the new item dialog.
        /// </summary>
        /// <param name="dialogCaption">The dialog caption.</param>
        /// <param name="folderName">Name of the folder.</param>
        /// <returns></returns>
        private string ShowNewItemDialog(string dialogCaption, string folderName, string extension)
        {
            using (AddNewItemDialog addNewItemDialog = new AddNewItemDialog())
            {
                addNewItemDialog.FileName = extension;
                addNewItemDialog.DialogCaption = dialogCaption;
                addNewItemDialog.FolderName = folderName;

                string fileName = string.Empty;
                if (addNewItemDialog.ShowDialog() != DialogResult.Cancel)
                {
                    fileName = addNewItemDialog.FileName;
                }

                return fileName;
            }
        }

        /// <summary>
        /// Displays the appropriate items based on the node selected.
        /// </summary>
        private void SetupContextMenu()
        {
            bool showFolderCommands = projectExplorer.SelectedNodeIsDirectory;
            bool showRootCommands = projectExplorer.RootNodeSelected;
            bool showTestCommands = projectExplorer.SelectedNodeIsTestable;

            addNewItemContextToolStripMenuItem.Visible = showFolderCommands | showRootCommands;
            folderToolStripSeparator.Visible = showFolderCommands | showRootCommands;
            newFolderToolStripMenuItem.Visible = showFolderCommands | showRootCommands;

            openContextToolStripItem.Visible = !showFolderCommands & !showRootCommands;
            openToolStripSeparator.Visible = !showFolderCommands & !showRootCommands ;
            
            runTestsContextToolStripMenuItem.Visible = showTestCommands;
            runTestsToolStripSeparator.Visible = runTestsContextToolStripMenuItem.Visible;

            deletedContextToolStripMenuItem.Visible = !showRootCommands;
            renameToolStripMenuItem.Visible = !showRootCommands;
            copyProjectExplorerContextToolStripMenuItem.Visible = !showRootCommands;

            RideMe.AddIns.Base.ApplicationContext.Current.UserInterfaceEvents.OnProjectExplorerContextMenuCreated(
                    new RideMe.AddIns.Events.UserInterfaceEventSource.ProjectExplorerContextMenuCreatedEventArgs(
                        projectExplorerContextMenuStrip,
                        projectExplorer.SelectedItemPath));
        }

        /// <summary>
        /// Called to reset when the operation takes place on another thread.
        /// </summary>
        private void ResetDisplay()
        {
            Application.UseWaitCursor = false;

            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(
                        delegate()
                        {
                            ResetDisplay();
                        }));
            }
            else
            {
                UpdateStatus(Resources.ReadyStatus);
            }
        }

        /// <summary>
        /// Updates the status.
        /// </summary>
        /// <param name="status">The status.</param>
        private void UpdateStatus(string status)
        {
            statusToolStripStatusLabel.Text = status;
        }

        /// <summary>
        /// Loads the recent projects.
        /// </summary>
        private void LoadRecentProjects()
        {
            IList<string> recentProjects = ProjectService.GetRecentProjects();

            if (recentProjects != null)
            {
                foreach (string projectName in recentProjects)
                {
                    CreateRecentProjectMenuItem(projectName, true);
                }
            }
        }

        /// <summary>
        /// Creates the recent project menu item.
        /// </summary>
        /// <param name="projectName">Name of the project.</param>
        /// <param name="addToBottom">if set to <c>true</c> [add to bottom].</param>
        private void CreateRecentProjectMenuItem(string projectName, bool addToBottom)
        {
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(
                    delegate()
                    {
                        CreateRecentProjectMenuItem(projectName, addToBottom);
                    }));
            }
            else
            {
                // If this is already in the list, ghost it.
                ToolStripMenuItem foundItem = FindDropDownItem(projectName, recentProjectsToolStripMenuItem);
                if (foundItem != null)
                {
                    recentProjectsToolStripMenuItem.DropDownItems.Remove(foundItem);
                }

                ToolStripMenuItem menuItem = new ToolStripMenuItem(projectName);
                menuItem.Click += new EventHandler(recentProjectMenuItem_click);

                // If this is a newly opened project, we want it at the top, yo.
                if (addToBottom)
                {
                    recentProjectsToolStripMenuItem.DropDownItems.Add(menuItem);
                }
                else
                {
                    recentProjectsToolStripMenuItem.DropDownItems.Insert(0, menuItem);
                }
            }
        }

        /// <summary>
        /// Finds the drop down item.
        /// </summary>
        /// <param name="search">The search criteria.</param>
        /// <param name="menuItem">The menu item.</param>
        /// <returns></returns>
        private ToolStripMenuItem FindDropDownItem(string search, ToolStripMenuItem menuItem)
        {
            foreach (ToolStripMenuItem item in menuItem.DropDownItems)
            {
                if (item.Text == search)
                {
                    return item;
                }
            }

            return null;
        }

        /// <summary>
        /// Removes the recent project menu item.
        /// </summary>
        /// <param name="path">The path.</param>
        private void RemoveRecentProjectMenuItem(string path)
        {
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(
                    delegate
                    {
                        RemoveRecentProjectMenuItem(path);
                    }));
            }
            else
            {
                foreach (ToolStripMenuItem menuItem in recentProjectsToolStripMenuItem.DropDownItems)
                {
                    if (menuItem.Text == path)
                    {
                        menuItem.Click -= new EventHandler(recentProjectMenuItem_click);
                        recentProjectsToolStripMenuItem.DropDownItems.Remove(menuItem);
                        break;
                    }
                }
            }
        }

        /// <summary>
        /// Displays the output window.
        /// </summary>
        private void DisplayOutputWindow()
        {
            if (InvokeRequired)
            {
               Invoke(new MethodInvoker(
                    delegate()
                    {
                        DisplayOutputWindow();
                    }));
            }
            else
            {
                outputDockControl.Open();
            }
        }

        /// <summary>
        /// Sets the form caption.
        /// </summary>
        /// <param name="caption">The caption.</param>
        private void SetFormCaption(string caption)
        {
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(
                    delegate
                    {
                        SetFormCaption(caption);
                    }));
            }
            else
            {
                this.Text = caption;
            }
        }

        /// <summary>
        /// Opens the project.
        /// </summary>
        /// <param name="path">The path.</param>
        private void OpenProject(string path)
        {
            Application.UseWaitCursor = true;

            try
            {
                InitializeProgressBar(path);
                UpdateStatus(Resources.LoadingStatus);

                ProjectService.CloseCurrentProject();
                // Setting this effectively triggers the project to open.
                ProjectService.ProjectPath = path;
            }
            catch (ArgumentException)
            {
                // The project no longer exists on disk. Does the user want to 
                // wax it out from the recent list.
                if (MessageService.ShowQuestion(this, Resources.RemoveProjectMessage) == DialogResult.Yes)
                {
                    ProjectService.RemoveRecentProject(path);
                }
            }
            finally
            {
                ResetDisplay();
            }
        }

        /// <summary>
        /// Opens the project file.
        /// </summary>
        private void OpenProjectFile()
        {
            Application.UseWaitCursor = true;

            try
            {
                ProjectService.AddOpenFile(projectExplorer.SelectedItemPath);
            }
            catch (AccessViolationException)
            { 
            }
            finally
            {
                Application.UseWaitCursor = false;
            }
        }

        /// <summary>
        /// Deletes the project file.
        /// </summary>
        private void DeleteProjectFile()
        {
            if (MessageService.ShowQuestion(this, Resources.DeleteConfirmMessage) != DialogResult.No)
            {
                try
                {
                    ProjectService.DeleteDocument(projectExplorer.SelectedItemPath);
                }
                catch (UnauthorizedAccessException)
                {
                    MessageService.ShowError(this, Resources.CantDeleteFileMessage);
                }
            }
        }

        /// <summary>
        /// Runs all unit and functional tests.
        /// </summary>
        /// <param name="trace">if set to <c>true</c> [trace].</param>
        private void RunAllTests(bool trace)
        {
            RunTests(delegate { ProjectService.RunAllTests(trace); });
        }

        /// <summary>
        /// Runs all functional tests.
        /// </summary>
        /// <param name="trace">if set to <c>true</c> [trace].</param>
        private void RunAllUnitTests(bool trace)
        {
            RunTests(delegate { ProjectService.RunAllUnitTests(trace); });
        }
        
        /// <summary>
        /// Runs all functional tests.
        /// </summary>
        /// <param name="trace">if set to <c>true</c> [trace].</param>
        private void RunAllFunctionalTests(bool trace)
        {
            RunTests(delegate { ProjectService.RunAllFunctionalTests(trace); });
        }

        /// <summary>
        /// Runs all integration tests.
        /// </summary>
        /// <param name="trace">if set to <c>true</c> [trace].</param>
        private void RunAllIntegrationTests(bool trace)
        {
            RunTests(delegate { ProjectService.RunAllIntegrationTests(trace); });
        }

        /// <summary>
        /// Runs all tests for a given path.
        /// </summary>
        /// <param name="path">A file or directory path.</param>
        /// <param name="trace">if set to <c>true</c> [trace].</param>
        private void RunAllTestsForPath(string path, bool trace)
        {
            if (FileSystemService.IsFile(path))
                RunTests(delegate { ProjectService.RunTestForFile(path); });
            else if (FileSystemService.IsDirectory(path))
                RunTests(delegate { ProjectService.RunTestsForDirectory(path, trace); });
        }
        
        delegate void TestOperation();
        
        /// <summary>
        /// Run a test operation, preparing the UI and restoring it after completion or error.
        /// </summary>
        /// <param name="op"></param>
        private void RunTests(TestOperation op)
        {
            Application.UseWaitCursor = true;
            UpdateStatus(Resources.TestingStatus);
            try
            {
                op();
                DisplayOutputWindow();
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
            finally
            {
                Application.UseWaitCursor = false;
            }
        }

        /// <summary>
        /// Generates the specified generator.
        /// </summary>
        /// <param name="generatorDialogCaption">The generator dialog caption.</param>
        /// <param name="generatorAction">The generator action.</param>
        /// <param name="generatorUsage">The generator usage.</param>
        private void Generate(string action, string usage, bool miscGenerator)
        {
            try
            {
                string generatorCommand = ShowGeneratorDialog(string.Format(Resources.GenerateDialogCaption, action), usage);

                if (generatorCommand.Trim().Length > 0)
                {
                    Application.UseWaitCursor = true;
                    UpdateStatus(Resources.GeneratingStatus);

                    ProjectService.GenerateNewItem(action, generatorCommand, miscGenerator);
                }
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }

        }

        /// <summary>
        /// Destroys the specified action.
        /// </summary>
        /// <param name="action">The action.</param>
        /// <param name="usage">The usage.</param>
        private void Destroy(string action, string usage, bool miscGenerator)
        {
          try 
          {
              string destroyCommand = ShowGeneratorDialog(string.Format(Resources.DestroyDialogCaption, action), usage);

              if (destroyCommand.Trim().Length > 0) 
              {
                  Application.UseWaitCursor = true;
                  UpdateStatus(Resources.DestroyingStatus);

                  ProjectService.DestroyItem(action, destroyCommand, miscGenerator);
              }
          }
          catch (Win32Exception) 
          {
              MessageService.ShowError(this, Resources.RubyNotFoundMessage);
              ResetDisplay();
          }
        }

        /// <summary>
        /// Stops the project.
        /// </summary>
        private void StopProject()
        {
            ProjectService.StopProject();
            notifyIcon.Visible = false;
            ResetDisplay();
        }

        private void DisplayFindReplaceDialog(bool replace)
        {
            FindReplaceDialog findAndReplaceDialog = new FindReplaceDialog();
            if (replace)
            {
                findAndReplaceDialog.SearchAndReplaceMode = SearchAndReplaceMode.Replace;
            }
            else
            {
                findAndReplaceDialog.SearchAndReplaceMode = SearchAndReplaceMode.Search;
            }

			// default to current selection if there is an open document
			string defaultFindWhatText = documentExplorer.ActiveTextEditorExists ? documentExplorer.GetCurrentSelectionOrNearestWord() : string.Empty;

			findAndReplaceDialog.FindWhatText = defaultFindWhatText;
            findAndReplaceDialog.FindAllStarted += new EventHandler(findAndReplaceDialog_FindAllStarted);
            findAndReplaceDialog.FindAllFinished += new EventHandler<RideMe.FindAndReplace.SearchAllFinishedEventArgs>(findAndReplaceDialog_FindAllFinished);
            findAndReplaceDialog.Disposed += new EventHandler(findAndReplaceDialog_Disposed);
            findAndReplaceDialog.Location = new Point(documentExplorer.Width - findAndReplaceDialog.Width, 100);
            findAndReplaceDialog.Show();
        }

        private void DisplayStatsDialog(string stats)
        {
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(
                    delegate
                    {
                        DisplayStatsDialog(stats);
                    }));
            }
            else
            {
                ResetDisplay();
                using (ProjectStatsDialog projectStatsDialog = new ProjectStatsDialog())
                {
                    projectStatsDialog.Stats = stats;
                    projectStatsDialog.ShowDialog();
                }
            }
        }

        private void DisplayAboutDialog()
        {
            using (AboutDialog aboutDialog = new AboutDialog())
            {
                aboutDialog.ShowDialog();
            }
        }

        private void AddNewThing(string dialogCaption, string extension)
        {
            if (projectExplorer.NodeSelected)
            {
                string fileName = ShowNewItemDialog(dialogCaption, projectExplorer.SelectedItemName, extension);

                if (fileName.Trim().Length > 0)
                {
                    string newFilePath = Path.Combine(projectExplorer.SelectedItemPath, fileName);
                    FileSystemService.SaveDocument(newFilePath, string.Empty);
                    ProjectService.AddOpenFile(newFilePath);
                }
            }
        }

        /// <summary>
        /// Handles opening a project.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void OpenProjectHandler(object sender, System.EventArgs e)
        {
			if (!string.IsNullOrEmpty(Options.Instance.LastProjectOpenedLocation))
			{
				folderBrowserDialog.SelectedPath = Options.Instance.LastProjectOpenedLocation;
			}

            if (folderBrowserDialog.ShowDialog() != DialogResult.Cancel)
            {
                Options.Instance.LastProjectOpenedLocation = folderBrowserDialog.SelectedPath;

                OpenProject(folderBrowserDialog.SelectedPath);
            }
        }

        private void InitializeProgressBar(string path)
        {
            try
            {
                toolStripProgressBar.Maximum = FileSystemService.GetNumberOfSubFolders(path) + FileSystemService.GetNumberOfFiles(path);
                toolStripProgressBar.Step = 1;
                toolStripProgressBar.Visible = true;
            }
            // handle the path not being valid
            catch (DirectoryNotFoundException)
            {}
        }

        private void RunMigration(bool trace)
        {
            try
            {
                Application.UseWaitCursor = true;
                UpdateStatus(Resources.RunningMigrationMessage);
                ProjectService.RunMigration(trace);
                DisplayOutputWindow();
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RakeNotFoundError);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles creating a new project.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void NewProjectHandler(object sender, System.EventArgs e)
        {
            using (NewProjectDialog newProjectDialog = new NewProjectDialog())
            {
                if (newProjectDialog.ShowDialog() != DialogResult.Cancel)
                {
                    Application.UseWaitCursor = true;
                    UpdateStatus(Resources.CreatingStatus);

                    try
                    {
                        ProjectService.CreateProject(newProjectDialog.ProjectLocation);
                    }
                    catch (Win32Exception)
                    {
                        MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                        ResetDisplay();
                    }
                    catch (FileNotFoundException)
                    {
                        MessageService.ShowError(this, Resources.RailsNotFoundMessage);
                        ResetDisplay();
                    }
                    catch (ArgumentException)
                    {
                        MessageService.ShowError(this, Resources.ProjectCouldntBeCreatedMessage);
                        ResetDisplay();
                    }
                }
            }
        }

        /// <summary>
        /// Handles closing a project.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void CloseProjectHandler(object sender, System.EventArgs e)
        {
            ProjectService.CloseCurrentProject();
            propertyGrid.SelectedObject = null;
        }

        /// <summary>
        /// Updates the close commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateCloseHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = ProjectService.ProjectOpen;
        }

        /// <summary>
        /// Handles exiting.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ExitHandler(object sender, System.EventArgs e)
        {
            this.Close();
        }

        /// <summary>
        /// Handles saving.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void SaveHandler(object sender, System.EventArgs e)
        {
            Application.UseWaitCursor = true;

            ProjectService.Save();

            ResetDisplay();
        }

        /// <summary>
        /// Handles saving.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void SaveAsHandler(object sender, System.EventArgs e)
        {
            using (SaveFileDialog saveAsDialog = new SaveFileDialog())
            {
                if (saveAsDialog.ShowDialog() == DialogResult.OK)
                {
                    ProjectService.SaveAs(documentExplorer.ActiveFilePath, saveAsDialog.FileName);
                }
            }
        }

        /// <summary>
        /// Handles saving all open files.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void SaveAllHandler(object sender, System.EventArgs e)
        {
            Application.UseWaitCursor = true;

            ProjectService.SaveAll();

            ResetDisplay();
        }

        /// <summary>
        /// Updates the save commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateSaveHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = ProjectService.NumberOfOpenFiles > 0;
        }

        /// <summary>
        /// Handles starting a project.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void StartHandler(object sender, System.EventArgs e)
        {
            try
            {
                Application.UseWaitCursor = true;
                ProjectService.RunProject();
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Updates the project open commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateProjectOpenHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = ProjectService.ProjectOpen;
        }

        /// <summary>
        /// Updates the project open and running commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateProjectOpenAndRunningHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = ProjectService.ProjectOpen & !ProjectService.ProjectRunning;
        }

        /// <summary>
        /// Handles adding a project item.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void AddProjectItemHandler(object sender, System.EventArgs e)
        {
            AddNewThing(Resources.NewItemCaption, string.Empty);
        }

        private void AddRhtmlPageHandler(object sender, System.EventArgs e)
        {
            AddNewThing(Resources.NewRhtmlPageCaption, Resources.RhtmlExtension);
        }

        private void AddRjsTemplateHandler(object sender, System.EventArgs e)
        {
            AddNewThing(Resources.NewRjsTemplateCaption, Resources.RjsExtension);
        }

        private void PrintHandler(object sender, System.EventArgs e)
        {
            documentExplorer.Print();
        }

        /// <summary>
        /// Handles adding a folder.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void AddFolderHandler(object sender, System.EventArgs e)
        {
            if ((projectExplorer.NodeSelected) & (projectExplorer.SelectedNodeIsDirectory))
            {
                string folderName = ShowNewItemDialog(Resources.NewFolderCaption, projectExplorer.SelectedItemName, string.Empty);

                if (folderName.Trim().Length > 0)
                {
                    string newFolderPath = Path.Combine(projectExplorer.SelectedItemPath, folderName);
                    FileSystemService.CreateDirectory(newFolderPath);
                }
            }
        }

        /// <summary>
        /// Handles deleting a file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void DeleteHandler(object sender, System.EventArgs e)
        {
            DeleteProjectFile();
        }

        /// <summary>
        /// Updates the delete commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateFileHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = projectExplorer.NodeSelected;
        }

        /// <summary>
        /// Updates the add project item command.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateAddProjectItemHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled =  ProjectService.ProjectOpen & projectExplorer.SelectedNodeIsDirectory;
        }

        /// <summary>
        /// Handles generating a controller.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void GenerateControllerHandler(object sender,  System.EventArgs e)
        {
            Generate(Resources.ControllerAction, Resources.ControllerGeneratorUsage, false);
        }

        /// <summary>
        /// Handles generating a model.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void GenerateModelHandler(object sender, System.EventArgs e)
        {
            Generate(Resources.ModelAction, Resources.ModelGeneratorUsage, false);
        }

        /// <summary>
        /// Handles generating a scaffold.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void GenerateScaffoldHandler(object sender, System.EventArgs e)
        {
            Generate(Resources.ScaffoldAction, Resources.ScaffoldGeneratorUsage, false);
        }

        /// <summary>
        /// Handles generating a datbase migration.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void GenerateMigrationHandler(object sender, System.EventArgs e)
        {
            Generate(Resources.MigrationAction, Resources.MigrationGeneratorUsage, false);
        }

        /// <summary>
        /// Handles generating a mailer.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void GenerateMailerHandler(object sender, System.EventArgs e)
        {
            Generate(Resources.MailerAction, Resources.MailerGeneratorUsage, false);
        }

        /// <summary>
        /// Handles generating a misc item.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void MiscGeneratorHandler(object sender, System.EventArgs e)
        {
            Generate(Resources.MiscAction, Resources.MiscGeneratorUsage, true);
        }

        /// <summary>
        /// Handles destroying a controller.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void DestroyControllerHandler(object sender, System.EventArgs e)
        {
            Destroy(Resources.ControllerAction, Resources.ControllerGeneratorUsage, false);
        }

        /// <summary>
        /// Handles destroying a model.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void DestroyModelHandler(object sender, System.EventArgs e)
        {
            Destroy(Resources.ModelAction, Resources.ModelGeneratorUsage, false);
        }

        /// <summary>
        /// Handles destroying a scaffold.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void DestroyScaffoldHandler(object sender, System.EventArgs e)
        {
            Destroy(Resources.ScaffoldAction, Resources.ScaffoldGeneratorUsage, false);
        }

        /// <summary>
        /// Handles destroying a Migration.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void DestroyMigrationHandler(object sender, System.EventArgs e)
        {
            Destroy(Resources.MigrationAction, Resources.MigrationGeneratorUsage, false);
        }

        /// <summary>
        /// Handles destroying a Mailer.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void DestroyMailerHandler(object sender, System.EventArgs e)
        {
            Destroy(Resources.MailerAction, Resources.MailerGeneratorUsage, false);
        }

        /// <summary>
        /// Handles destroying a misc item.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void DestroyMiscGeneratorHandler(object sender, System.EventArgs e)
        {
            Destroy(Resources.MiscAction, Resources.MiscGeneratorUsage, true);
        }

        /// <summary>
        /// Handles stopping a project.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void StopProjectHandler(object sender, System.EventArgs e)
        {
            StopProject();
        }

        /// <summary>
        /// Updates the stop project commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateStopProjectHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = ProjectService.ProjectRunning;
        }

        /// <summary>
        /// Handles opening a file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void OpenFileHandler(object sender, System.EventArgs e)
        {
            OpenProjectFile();
        }

        /// <summary>
        /// Handles renaming a node.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RenameNodeHandler(object sender, System.EventArgs e)
        {
            projectExplorer.BeginEditNode();
        }

        /// <summary>
        /// Handles the redo command.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RedoHandler(object sender, System.EventArgs e)
        {
            documentExplorer.Redo();
        }

        /// <summary>
        /// Updates the redo commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateRedoHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = documentExplorer.CanRedo;
        }

        /// <summary>
        /// Handles the undo command.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UndoHandler(object sender, System.EventArgs e)
        {
            documentExplorer.Undo();
        }

        /// <summary>
        /// Updates the undo commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateUndoHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = documentExplorer.CanUndo;
        }

        /// <summary>
        /// Handles the cut commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void CutHandler(object sender, System.EventArgs e)
        {
            documentExplorer.Cut();
        }

        /// <summary>
        /// Handles the command commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void CopyHandler(object sender, System.EventArgs e)
        {
            if (DocumentExplorerSelected)
            {
                documentExplorer.Copy();
            }
            else
            {
                projectExplorer.CopySelectedFile();
            }
        }

        /// <summary>
        /// Handles the paste commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void PasteHandler(object sender, System.EventArgs e)
        {
            if (DocumentExplorerSelected)
            {
                documentExplorer.Paste();
            }
            else
            {
                projectExplorer.PasteFile();
            }
        }

        /// <summary>
        /// Updates the copy paste commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateCanCopyPasteHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = documentExplorer.CanCutCopyPaste || projectExplorer.NodeSelected;
        }

        private void UpdateRubyFileSelectedHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = documentExplorer.RubyFileActive;
        }

        /// <summary>
        /// Updates the cut commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateCanCutHandler(object sender, System.EventArgs e)
        {
            // Cut only works in the document explorer.
            ((Command)sender).Enabled = documentExplorer.CanCutCopyPaste & ProjectService.NumberOfOpenFiles != 0;
        }

        /// <summary>
        /// Handles opening a file.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void OpenNonProjectFileHander(object sender, System.EventArgs e)
        {
            using (OpenFileDialog openFileDialog = new OpenFileDialog())
            {
                openFileDialog.Filter = "All files (*.*) | *.*";
				openFileDialog.InitialDirectory = ProjectService.ProjectPath;

                if (openFileDialog.ShowDialog() != DialogResult.Cancel)
                {
                    ProjectService.AddOpenFile(openFileDialog.FileName);
                }
            }
        }

        /// <summary>
        /// Updates the recent projects commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateRecentProjectsHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = (ProjectService.RecentProjects != null) && (ProjectService.RecentProjects.Count > 0);
        }

        /// <summary>
        /// Handles viewing the project explorer commands
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ViewProjectExplorerHandler(object sender, System.EventArgs e)
        {
            projectExplorerDockControl.Open();
        }

        /// <summary>
        /// Handles viewing the output commands
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ViewOutputHandler(object sender, System.EventArgs e)
        {
            DisplayOutputWindow();
        }

        /// <summary>
        /// Handles the view properties commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ViewPropertiesWindowHandler(object sender, System.EventArgs e)
        {
            propertiesDockControl.Open();
        }

        /// <summary>
        /// Handles the show options commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ShowOptionsHandler(object sender, System.EventArgs e)
        {
            using (OptionsDialog optionsDialog = new OptionsDialog())
            {
                optionsDialog.ShowDialog();
            }
        }

        /// <summary>
        /// Handles the run all tests command.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RunAllTestsHandler(object sender, EventArgs e)
        {
            try
            {
                RunAllTests(false);
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles the run all unit tests command.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RunAllUnitTestsHandler(object sender, System.EventArgs e)
        {
            try
            {
                RunAllUnitTests(false);
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles the run all functional tests commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RunAllFunctionalTestsHandler(object sender, System.EventArgs e)
        {
            try
            {
                RunAllFunctionalTests(true);
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles the run all integration tests commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RunAllIntegrationTestsHandler(object sender, System.EventArgs e)
        {
            try
            {
                RunAllIntegrationTests(false);
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles the run all integration tests with trace commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RunAllIntegrationTestsWithTraceHandler(object sender, System.EventArgs e)
        {
            try
            {
                RunAllIntegrationTests(true);
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles the run all tests with trace command
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RunAllTestsWithTraceHandler(object sender, System.EventArgs e)
        {
            try
            {
                RunAllTests(true);
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles the Run all unit tests with trace command.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RunAllUnitTestsWithTraceHandler(object sender, System.EventArgs e)
        {
            try
            {
                RunAllUnitTests(true);
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles the Run all functional tests with trace command
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RunAllFunctionalTestsWithTraceHandler(object sender, System.EventArgs e)
        {
            try
            {
                RunAllFunctionalTests(true);
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles running specific tests for a path.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void RunTestsForPathHandler(object sender, System.EventArgs e)
        {
            try
            {
                RunAllTestsForPath(projectExplorer.SelectedItemPath, false);
            }
            catch (Win32Exception)
            {
                MessageService.ShowError(this, Resources.RubyNotFoundMessage);
                ResetDisplay();
            }
        }

        /// <summary>
        /// Handles showing the model.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void GoToModelHandler(object sender, System.EventArgs e)
        {
            string entityPath = string.Empty;

            if (projectExplorer.InControllersNode)
            {
                try
                {
                    entityPath = MvcHelper.FindModelPathForController(projectExplorer.SelectedItemPath, ProjectService.ProjectPath);
                }
                catch (IOException)
                {
                    MessageService.ShowInformationalMessage(this, string.Format(Resources.ModelDoesNotExistMessage, Resources.ControllerAction));
                    return;
                }
            }
            else if (projectExplorer.InViewsNode)
            {
                try
                {
                    entityPath = MvcHelper.FindModelPathForView(projectExplorer.SelectedItemParentName, ProjectService.ProjectPath);
                }
                catch (IOException)
                {
                    MessageService.ShowInformationalMessage(this, string.Format(Resources.ModelDoesNotExistMessage, Resources.View));
                    return;
                }
            }
            else
            {
                return;
            }

            ProjectService.AddOpenFile(entityPath);
        }

        /// <summary>
        /// Updates the go to model context item.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateGoToModelHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = projectExplorer.InControllersNode | projectExplorer.InViewsNode;
        }

        /// <summary>
        /// Handles showing the view.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void GoToViewHandler(object sender, System.EventArgs e)
        {
            if (projectExplorer.InControllersNode)
            {
                if (!documentExplorer.MethodSelected)
                {
                    MessageService.ShowError(this, Resources.NoMethodSelectedMessage);
                    return;
                }

                try
                {
                    ProjectService.AddOpenFile(MvcHelper.FindViewPathForController(projectExplorer.SelectedItemPath, documentExplorer.SelectedMethodName, ProjectService.ProjectPath));
                }
                catch (IOException)
                {
                    MessageService.ShowInformationalMessage(this, Resources.ViewDoesNotExistMessage);
                }
            }
        }

        /// <summary>
        /// Updates the go to view command.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateGoToViewHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = projectExplorer.InControllersNode;
        }

        /// <summary>
        /// Handles showing the controller.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void GoToControllerHandler(object sender, System.EventArgs e)
        {
            string entityPath = string.Empty;

            if (projectExplorer.InModelsNode)
            {
                try
                {
                    entityPath = MvcHelper.FindControllerPathForModel(projectExplorer.SelectedItemPath, ProjectService.ProjectPath);
                }
                catch (IOException)
                {
                    MessageService.ShowInformationalMessage(this, string.Format(Resources.ModelDoesNotExistMessage, Resources.ControllerAction));
                    return;
                }
            }
            else if (projectExplorer.InViewsNode)
            {
                try
                {
                    entityPath = MvcHelper.FindControllerPathForView(projectExplorer.SelectedItemParentName, ProjectService.ProjectPath);
                }
                catch (IOException)
                {
                    MessageService.ShowInformationalMessage(this, string.Format(Resources.ModelDoesNotExistMessage, Resources.View));
                    return;
                }
            }
            else
            {
                return;
            }
            ProjectService.AddOpenFile(entityPath);

        }

        /// <summary>
        /// Updates the go to controller command.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateGoToControllerHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = projectExplorer.InModelsNode | projectExplorer.InViewsNode;
        }

        /// <summary>
        /// Handles the go to file commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void GoToFileHandler(object sender, System.EventArgs e)
        {
            using (GoToFileDialog goToFileDialog = new GoToFileDialog())
            {
                if (goToFileDialog.ShowDialog() == DialogResult.OK)
                {
                    documentExplorer.Focus();
                }
            }
        }

        /// <summary>
        /// Handles toggling coments on or off.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ToggleCommentHandler(object sender, System.EventArgs e)
        {
            documentExplorer.ToggleComment();
        }

        private void ClearOutputWindowHandler(object sender, System.EventArgs e)
        {
            outputWindow.ClearOutput();
        }

        private void ReplaceTabsWithSpacesHandler(object sender, System.EventArgs e)
        {
            documentExplorer.ConvertTabsToSpaces();
        }

        /// <summary>
        /// Handles preparing the project for Unix deployment.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void PrepareForUnixHandler(object sender, System.EventArgs e)
        {
            ProjectService.PrepareForServer(true);
        }

        /// <summary>
        /// Handles preparing the project for Windows deployment.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void PrepareForWindowsHandler(object sender, System.EventArgs e)
        {
            ProjectService.PrepareForServer(false);
        }

        /// <summary>
        /// Updates the toggle comment commands.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void UpdateToggleCommentHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = documentExplorer.IsSomethingSelected;
        }

        /// <summary>
        /// Handles viewing the project stats.
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ViewProjectStatsHandler(object sender, System.EventArgs e)
        {
            Application.UseWaitCursor = true;
            UpdateStatus(Resources.GettingStatsStatus);
            ProjectService.GetProjectStats();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void FindHandler(object sender, System.EventArgs e)
        {
            DisplayFindReplaceDialog(false);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ReplaceHandler(object sender, System.EventArgs e)
        {
            DisplayFindReplaceDialog(true);
        }

        private void AboutHandler(object sender, System.EventArgs e)
        {
            DisplayAboutDialog();
        }

        private void RailsDocumentationHandler(object sender, System.EventArgs e)
        {
            Process.Start(HelpPath);
        }

		private void WindowCloseHandler(object sender, System.EventArgs e)
		{
			documentExplorer.CloseWindow();
		}

		private void UpdateWindowCloseHandler(object sender, System.EventArgs e)
		{
			((Command)sender).Enabled = documentExplorer.CanCloseActiveWindow;
		}

		private void WindowCloseAllHandler(object sender, System.EventArgs e)
		{
			documentExplorer.CloseAll();
		}

		private void UpdateWindowCloseAllHandler(object sender, System.EventArgs e)
		{
			((Command)sender).Enabled = documentExplorer.CanCloseAll;
		}

		private void WindowCloseAllButThisHandler(object sender, System.EventArgs e)
		{
			documentExplorer.CloseAllButCurrent();
		}

		private void UpdateWindowCloseAllButThisHandler(object sender, System.EventArgs e)
		{
			((Command)sender).Enabled = documentExplorer.CanCloseAll;
		}

		private void WindowSplitHandler(object sender, System.EventArgs e)
		{
			documentExplorer.ActiveTextEditor.Split();
		}

		private void UpdateWindowSplitHandler(object sender, System.EventArgs e)
		{
			((Command)sender).Enabled = documentExplorer.ActiveTextEditor != null;
		}

        private void CheckSyntaxHandler(object sender, System.EventArgs e)
        {
            RubyProcess ruby = new RubyProcess();
            ruby.SyntaxCheckComplete += new EventHandler<CheckSyntaxEventArgs>(ruby_SyntaxCheckComplete);
            ruby.ErrorReceived += new EventHandler<DataReceivedEventArgs>(ErrorReceivedHandler);

            string selectedFile;

            if (DocumentExplorerSelected)
            {
                selectedFile = documentExplorer.ActiveFilePath;
            }
            else
            {
                selectedFile = projectExplorer.SelectedItemPath;
            }
            ruby.CheckSyntax(selectedFile);

        }


        private void UpdateCheckSyntaxHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = false;

            if (DocumentExplorerSelected && documentExplorer.RubyFileActive)
            {
                ((Command)sender).Enabled = true;
            }
            else
            {
                if (projectExplorer.RubyFileSelected)
                {
                    ((Command)sender).Enabled = true;
                }
            }
        }

        private void CodeSnippetManagerHandler(object sender, System.EventArgs e)
        {
            using (SnippetManagerDialog snippetManagerDialog = new SnippetManagerDialog())
            {
                snippetManagerDialog.ShowDialog();
            }
        }

        private void ToggleFoldHandler(object sender, System.EventArgs e)
        {
            ICSharpCode.TextEditor.Actions.ToggleFolding tf = new ICSharpCode.TextEditor.Actions.ToggleFolding();
            tf.Execute(documentExplorer.ActiveTextEditor.ActiveTextAreaControl.TextArea);
        }

        private void ToggleAllFoldingHandler(object sender, System.EventArgs e)
        {
            ICSharpCode.TextEditor.Actions.ToggleAllFoldings tf = new ICSharpCode.TextEditor.Actions.ToggleAllFoldings();
            tf.Execute(documentExplorer.ActiveTextEditor.ActiveTextAreaControl.TextArea);
        }

        private void ShowDefinitionsOnlyHandler(object sender, System.EventArgs e)
        {
            ICSharpCode.TextEditor.Actions.ShowDefinitionsOnly tf = new ICSharpCode.TextEditor.Actions.ShowDefinitionsOnly();
            tf.Execute(documentExplorer.ActiveTextEditor.ActiveTextAreaControl.TextArea);
        }

        private void RunMigrationHandler(object sender, System.EventArgs e)
        {
            RunMigration(false);
        }

        private void RunMigrationWithTraceHandler(object sender, System.EventArgs e)
        {
            RunMigration(true);
        }

        private void UpdateFileOpenHandler(object sender, System.EventArgs e)
        {
            ((Command)sender).Enabled = ProjectService.OpenFiles.Count > 0;
        }

        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Form.Closing"></see> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.ComponentModel.CancelEventArgs"></see> that contains the event data.</param>
        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            // If they chose to cancel closing a document, don't close the app.
            e.Cancel = !documentExplorer.CheckAllEditors();

            ProjectService.StopServer();
            // Do this 'cause running tests changes the directory for Rake.
            Environment.CurrentDirectory = Path.GetDirectoryName(Application.ExecutablePath);
            ProjectService.SaveRecentProjects();
            FileSystemService.SaveDocument(Resources.LayoutFileName, sandDockManager.GetLayout());
            if (Options.Instance.LoadLastProjectAtStartUp)
            {
                // Save an open files, so they can be display when the app loads.
                Options.Instance.PreviouslyOpenedFiles = ProjectService.OpenFiles;
            }
            // We don't want any classes to receive this event at this point.
            // It just causes problems, a'ight?
            Options.Instance.SuppressChangeEvent = true;
            Options.Instance.SaveOptions(Options.Instance);
            Application.Exit();
        }

        /// <summary>
        /// Handles the Opening event of the projectExplorerContextMenuStrip control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>
        private void projectExplorerContextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            // We don't want to show the context menu if no node is selected.
            if (!projectExplorer.NodeSelected)
            {
                e.Cancel = true;
                return;
            }

            SetupContextMenu();
        }

        /// <summary>
        /// Handles the ProjectLoaded event of the projectExplorer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void projectExplorer_ProjectLoaded(object sender, EventArgs e)
        {
            ResetDisplay();
        }

        /// <summary>
        /// Handles the GeneratingComplete event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ProjectService_GeneratingComplete(object sender, EventArgs e)
        {
            ResetDisplay();
        }

        /// <summary>
        /// Handles the LastDocumentClosed event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ProjectService_LastDocumentClosed(object sender, EventArgs e)
        {
            // The last document tab was closed, so clear the line column numbers.
            UpdateLineColumnStatus(string.Empty, string.Empty);
        }

        /// <summary>
        /// Handles the EditorCaretPositionChanged event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:RideMe.Core.CaretPositionChangedEventArgs"/> instance containing the event data.</param>
        private void ProjectService_EditorCaretPositionChanged(object sender, CaretPositionChangedEventArgs e)
        {
            UpdateLineColumnStatus(string.Format(Resources.LineDisplayText, e.Line.ToString()), string.Format(Resources.ColumnDisplayText, e.Column.ToString()));
        }

        /// <summary>
        /// Handles the RecentProjectAdded event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:RideMe.Core.ProjectPathChangedEventArgs"/> instance containing the event data.</param>
        private void ProjectService_RecentProjectAdded(object sender, ProjectPathChangedEventArgs e)
        {
            CreateRecentProjectMenuItem(e.NewProjectPath, false);
        }

        /// <summary>
        /// Handles the RecentProjectRemoved event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:RideMe.Core.ProjectPathChangedEventArgs"/> instance containing the event data.</param>
        private void ProjectService_RecentProjectRemoved(object sender, ProjectPathChangedEventArgs e)
        {
            RemoveRecentProjectMenuItem(e.NewProjectPath);
        }

        /// <summary>
        /// Handles the FileDeleted event of the ProjectService
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectService_FileDeleted(object sender, ProjectFileEventArgs e)
        {
            RideMe.AddIns.Base.ApplicationContext.Current.ProjectEvents.OnFileDeleted(new RideMe.AddIns.Events.ProjectEventSource.FileEventArgs(e.FilePath));
        }

        /// <summary>
        /// Handles the FileClosed event of the ProjectService
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectService_FileClosed(object sender, ProjectFileEventArgs e)
        {
            RideMe.AddIns.Base.ApplicationContext.Current.ProjectEvents.OnFileClosed(new RideMe.AddIns.Events.ProjectEventSource.FileEventArgs(e.FilePath));
        }

        /// <summary>
        /// Handles the FileOpened event of the ProjectService
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectService_FileOpened(object sender, ProjectFileEventArgs e)
        {
            RideMe.AddIns.Base.ApplicationContext.Current.ProjectEvents.OnFileOpened(new RideMe.AddIns.Events.ProjectEventSource.FileEventArgs(e.FilePath));
			if (documentExplorer.ActiveTextEditorExists)
			{
				documentExplorer.ActiveTextEditor.AllowDrop = true;
				documentExplorer.ActiveTextEditor.DragDrop += new DragEventHandler(ActiveTextEditor_DragDrop);
			}
        }

		void ActiveTextEditor_DragDrop(object sender, DragEventArgs e)
		{
			
		}

        /// <summary>
        /// Handles the click event of the recentProjectMenuItem control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void recentProjectMenuItem_click(object sender, EventArgs e)
        {
            OpenProject(((ToolStripMenuItem)sender).Text);
        }

        /// <summary>
        /// Handles the ProjectClosed event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ProjectService_ProjectClosed(object sender, EventArgs e)
        {
            SetFormCaption(Application.ProductName);
            StopProject();
            RideMe.AddIns.Base.ApplicationContext.Current.ProjectEvents.OnProjectClosed(new RideMe.AddIns.Events.ProjectEventSource.FileEventArgs(string.Empty));
        }

        /// <summary>
        /// Handles the ProjectPathChanged event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:RideMe.Core.ProjectPathChangedEventArgs"/> instance containing the event data.</param>
        private void ProjectService_ProjectPathChanged(object sender, ProjectPathChangedEventArgs e)
        {
            try
            {
                SetFormCaption(e.NewProjectPath + " - " + Application.ProductName);
            }
            catch (ArgumentException)
            {
            }
        }

        /// <summary>
        /// Handles the WebServerStarted event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ProjectService_WebServerStarted(object sender, EventArgs e)
        {
            DisplayServerBallon();
        }

        /// <summary>
        /// Handles the KeyDown event of the projectExplorer control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.Windows.Forms.KeyEventArgs"/> instance containing the event data.</param>
        private void projectExplorer_KeyDown(object sender, KeyEventArgs e)
        {
            if (!projectExplorer.NodeSelected) return;

            // Might need to change this to a switch soon. 
            if (e.KeyCode == Keys.Enter)
            {
                OpenProjectFile();
            }
            else if (e.KeyCode == Keys.Delete)
            {
                DeleteProjectFile();
            }
            else if (e.KeyCode == Keys.F2)
            {
                projectExplorer.BeginEditNode();
            }
        }

        /// <summary>
        /// Handles the Opening event of the documentExplroerContextMenuStrip control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>
        
        // this sub was mispelled as indicated in the "Handles" comment above.  
        // it doesn't appear that this is used currently in any event
        // Jason H.
        private void documentExplorerContextMenuStrip_Opening(object sender, CancelEventArgs e)
        {
            // Don't show the context menu if there aren't any open files.
            if (ProjectService.NumberOfOpenFiles == 0)
            {
                e.Cancel = true;
            }
        }

        /// <summary>
        /// Handles the SelectedFileChanged event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:RideMe.Core.SelectedFileChangedEventArgs"/> instance containing the event data.</param>
        private void ProjectService_SelectedFileChanged(object sender, SelectedFileChangedEventArgs e)
        {
            propertyGrid.SelectedObject = e;
            if(e!=null)
                RideMe.AddIns.Base.ApplicationContext.Current.ProjectEvents.OnFileSelected(new RideMe.AddIns.Events.ProjectEventSource.FileEventArgs(e.Path));
        }

        /// <summary>
        /// Handles the FileRenamed event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:RideMe.Core.FileRenameEventArgs"/> instance containing the event data.</param>
        private void ProjectService_FileRenamed(object sender, FileRenameEventArgs e)
        {
            if (propertyGrid.SelectedObject != null)
            {
                SelectedFileChangedEventArgs castedSelectedObject = propertyGrid.SelectedObject as SelectedFileChangedEventArgs;
                if (castedSelectedObject != null)
                {
                    // Normally setting this actually renames the files.
                    // The file has already been renamed, so just update the display.
                    castedSelectedObject.RenameFile = false;
                    castedSelectedObject.FileName = Path.GetFileName(e.NewFileName);
                    castedSelectedObject.Path = e.NewFilePath;

                    propertyGrid.Refresh();
                }
            }
            RideMe.AddIns.Base.ApplicationContext.Current.ProjectEvents.OnFileRenamed(new RideMe.AddIns.Events.ProjectEventSource.RenamedFileEventArgs(e.OldFilePath, e.NewFilePath));
        }

        /// <summary>
        /// Handles the TabChanged event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:RideMe.Core.ProjectFileEventArgs"/> instance containing the event data.</param>
        private void ProjectService_TabChanged(object sender, ProjectFileEventArgs e)
        {
            projectExplorer.FocusSpecificNodeByPath(e.FilePath);
        }

        /// <summary>
        /// Handles the PreparedForServer event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:RideMe.Core.ProjectFileEventArgs"/> instance containing the event data.</param>
        private void ProjectService_PreparedForServer(object sender, ProjectFileEventArgs e)
        {
            MessageService.ShowInformationalMessage(this, Resources.PrepareCompleteMessage);
        }

        /// <summary>
        /// Handles the StatsRecieved event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:RideMe.Core.RakeStatsEventArgs"/> instance containing the event data.</param>
        private void ProjectService_StatsRecieved(object sender, RakeEventArgs e)
        {
            // Often the stats come back blank the first time, so try agian in that case.
            if (string.IsNullOrEmpty(e.Stats))
            {
                ViewProjectStatsHandler(this, EventArgs.Empty);
            }
            else
            {
                DisplayStatsDialog(e.Stats);
            }
        }

        /// <summary>
        /// Handles the ProjectLoaded event of the ProjectService control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="T:System.EventArgs"/> instance containing the event data.</param>
        private void ProjectService_ProjectLoaded(object sender, ProjectLoadedEventArgs e)
        {
            ResetDisplay();
            Application.UseWaitCursor = false;
            RideMe.AddIns.Base.ApplicationContext.Current.ProjectEvents.OnProjectOpened(new RideMe.AddIns.Events.ProjectEventSource.FileEventArgs(e.Path));
        }

        private void findAndReplaceDialog_Disposed(object sender, EventArgs e)
        {
            ((FindReplaceDialog)sender).FindAllStarted -= new EventHandler(findAndReplaceDialog_FindAllStarted);
            ((FindReplaceDialog)sender).FindAllFinished -= new EventHandler<RideMe.FindAndReplace.SearchAllFinishedEventArgs>(findAndReplaceDialog_FindAllFinished);
        }

        private void findAndReplaceDialog_FindAllStarted(object sender, EventArgs e)
        {
            UpdateStatus(Resources.SearchingFilesStatus);
            Application.UseWaitCursor = true;
        }

        private void findAndReplaceDialog_FindAllFinished(object sender, RideMe.FindAndReplace.SearchAllFinishedEventArgs e)
        {
            ResetDisplay();
            Application.UseWaitCursor = false;
            findResultsWindow.DisplayResults(e.Pattern, e.Results);
            findResultsDockControl.Open();
        }

        private void ruby_SyntaxCheckComplete(object sender, CheckSyntaxEventArgs e)
        {
            if (InvokeRequired)
            {
                Invoke(new MethodInvoker(
                        delegate()
                        {
                            ruby_SyntaxCheckComplete(sender, e);
                        }));
            }
            else
            {
                if (e.Pass)
                {
                    MessageService.ShowInformationalMessage(this, Resources.SyntaxCheckPassed);
                }
                else
                {
                    MessageService.ShowError(this, Resources.SyntaxCheckFailedMessage);
                }
            }
        }

        private void projectExplorer_ProjectItemFound(object sender, EventArgs e)
        {
            if (toolStripProgressBar.Value != toolStripProgressBar.Maximum)
            {
                toolStripProgressBar.PerformStep();
            }
            else
            {
                toolStripProgressBar.Visible = false;
                toolStripProgressBar.Value = 0;
            }
        }

        private void ProjectService_WebServerStarting(object sender, EventArgs e)
        {
            UpdateStatus(Resources.StartingServerMessage);
        }

        /// <summary>
        /// Respond to a ProjectStarted event by opening a browser tab.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectService_ProjectStarted(object sender, EventArgs e)
        {
            if (Options.Instance.LaunchInternalBrowser)
            {
                OpenBrowser();
            }

            Application.UseWaitCursor = false;
            ResetDisplay();
        }

        /// <summary>
        /// Respond to a ProjectStopped event by closing the browser tab.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ProjectService_ProjectStopped(object sender, EventArgs e)
        {
            CloseBrowser();
        }

        private void ErrorReceivedHandler(object sender, DataReceivedEventArgs e)
        {
            Invoke(new MethodInvoker(
                delegate
                {
                    outputWindow.AppendOutput(e.Data);
                    DisplayOutputWindow();
                }));
        }

        private void ProjectService_LogErrorFound(object sender, LogFileWatcher.RailsLogFileEventArgs e)
        {
			if (InvokeRequired)
			{
				BeginInvoke(new EventHandler<LogFileWatcher.RailsLogFileEventArgs>(ProjectService_LogErrorFound), sender, e);
				return;
			}

			if (!Options.Instance.LaunchInternalBrowser)
			{
				OpenFileAtLine(e.FileName, e.LineNumber);
			}
			else
			{
				runtimeErrorToolStripLabel.Visible = true;
				runtimeErrorToolStripLabel.Tag = e;
			}
        }

		private void runtimeErrorToolStripLabel_Click(object sender, EventArgs e)
		{
			LogFileWatcher.RailsLogFileEventArgs args = runtimeErrorToolStripLabel.Tag as LogFileWatcher.RailsLogFileEventArgs;

			if (args != null)
			{
				OpenFileAtLine(args.FileName, args.LineNumber);
				runtimeErrorToolStripLabel.Visible = false;
			}
		}

		private void OpenFileAtLine(string filename, int lineNumber)
		{
			ProjectService.AddOpenFile(filename);
			
			if (documentExplorer.ActiveTextEditor != null && documentExplorer.ActiveFilePath == filename)
			{
				documentExplorer.ActiveTextEditor.ActiveTextAreaControl.Caret.Line = lineNumber - 1;
			}

		}
   }
}
